home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / util / libs / mufs_usergroup.lha / usergroup / credential.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  20KB  |  759 lines

  1. RCS_ID_C="$Id: credential.c,v 4.2 1994/05/18 15:43:02 ppessi Exp $";
  2. /*
  3.  * credential.c --- handle credentials
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * This file is part of the AmiTCP/IP User Library.
  8.  *
  9.  * Copyright ⌐ 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
  10.  *                  Helsinki University of Technology, Finland.
  11.  *
  12.  * Created      : Wed Sep 15 01:25:26 1993 ppessi
  13.  * Last modified: Wed May 18 18:42:43 1994 ppessi
  14.  */
  15.  
  16. #include "base.h"
  17. #include "credential.h"
  18. #include "libfunc.h"
  19.  
  20. #include <exec/memory.h>
  21. #include <exec/alerts.h>
  22. #include <string.h>
  23. #include <assert.h>
  24.  
  25. struct CredentialResource *CredentialBase;
  26.  
  27. #ifdef notyet
  28. typedef struct CredentialResource *(*resident_init_fp)(void);
  29.  
  30. /*
  31.  * Create credential resource
  32.  */
  33. struct CredentialResource *CredentialInit(const char *name)
  34. {
  35.   BPTR resseg = LoadSeg(_PATH_CREDENTIAL);
  36.  
  37.   if (resseg) {
  38.     resident_init_fp initf = (resident_init_fp)((LONG *)(resseg << 2) + 1);
  39.     struct CredentialResource *res = initf();
  40.  
  41.     if (res)
  42.       return res;
  43.  
  44.     UnLoadSeg(resseg);
  45.   }
  46.  
  47.   return NULL;
  48. }
  49. #endif
  50.  
  51. /****** usergroup.library/getspgrp ********************************************
  52.  
  53.     NAME
  54.         getpgrp - get process group identification
  55.  
  56.     SYNOPSIS
  57.         #include <libraries/usergroup.h>
  58.  
  59.         sessionid = getpgrp()
  60.             D0
  61.         pid_t getpgrp(void);
  62.  
  63.     FUNCTION
  64.         The getpgrp() function returns the process group id for the current
  65.         process.  Currently, the process group ID is the same as the session
  66.         ID. The 0 is valid process group ID for console session.
  67.  
  68.     RESULTS
  69.         Upon successful completion, the value of the process group ID is
  70.         returned.  Otherwise, a value of -1 is returned and an error code is
  71.         stored to global errno location.
  72.  
  73.     ERRORS
  74.         [ESRCH]   The calling process don't belong to any process group.
  75.  
  76.     SEE ALSO
  77.          setsid(),  exec.library/FindTask()
  78.  
  79. ******************************************************************************
  80. */
  81.  
  82. SAVEDS ASM pid_t R_getpgrp(void)
  83. {
  84.   struct proc *p = procfind(NULL);
  85.  
  86.   return p->p_session->s_leader;
  87. }
  88.  
  89. /****** usergroup.library/setsid *********************************************
  90.  
  91.     NAME
  92.         setsid - create a new session
  93.  
  94.     SYNOPSIS
  95.         #include <unistd.h>
  96.  
  97.         sessionid = setsid()
  98.             D0
  99.         pid_t setsid(void);
  100.  
  101.     FUNCTION
  102.         The setsid() function creates a new session when the calling
  103.         process is not a process group leader.  The calling process
  104.         then becomes the session leader of this session and the only
  105.         process in the new session.
  106.  
  107.     RESULTS
  108.         Upon successful completion, the value of the new session ID is
  109.         returned.  Otherwise, a value of -1 is returned and an error
  110.         code is  stored to global errno location.
  111.  
  112.     ERRORS
  113.         [EPERM]   The calling process is already a session leader.
  114.  
  115.     SEE ALSO
  116.          getpgrp()
  117.  
  118. ******************************************************************************
  119. */
  120.  
  121. SAVEDS ASM pid_t R_setsid(void)
  122. {
  123. #ifdef notyet
  124.   pid_t pid = (pid_t)FindTask(NULL);
  125.   struct proc *p = procfind(pid);
  126.   int error;
  127.  
  128.   if (p->p_session->s_leader == pid) {
  129.     error = EPERM;
  130.   } else {
  131.     struct session *session;
  132.  
  133.     while (!(session = AllocMem(sizeof(*session), MEMF_CLEAR|MEMF_PUBLIC))) {
  134.       Alert(AG_NoMemory | UG_CredRes);
  135.       Wait(0L);
  136.     }
  137.     InitList((struct List *)session->s_pgrpl);
  138.     Forbid();
  139.     p = proccopy(p, pid);
  140.     p->p_ucred->cr_ref++;
  141.     p->p_ucred = crcopy(p->p_ucred);
  142.  
  143.     /* Remove from old process group */
  144.     rempgrp(p);
  145.     p->p_session = session;
  146.     MinAddHead(session->s_pgrpl, p->p_pgrp);
  147.     session->s_consoletask = GetConsoleTask();
  148.     session->s_leader = pid;
  149.     Permit();
  150.     return pid;
  151.   }
  152.  
  153.   SetErrno(error);
  154.   return -1;
  155. #endif
  156.   return 0;
  157. }
  158.  
  159. #ifdef notyet
  160. /*
  161.  * Remove a process from session's process group and
  162.  * free session if last process is removed
  163.  */
  164. void
  165. rempgrp(struct proc *p)
  166. {
  167.   Forbid();
  168.   /* Free the session structure if the last task in process group dies */
  169.   MinRemove((struct Node *)p->p_pgrp);
  170.   if (IsMinListEmpty(p->p_session->s_pgrpl)) {
  171.     FreeMem(p->p_session, sizeof(*p->p_session));
  172.   } else if (p->p_session->s_leader == (pid_t)p->p_task) {
  173.   }
  174.   Permit();
  175. }
  176. #endif
  177.  
  178. /*
  179.  * Check super-user
  180.  */
  181. int
  182. suser(struct ucred *cred)
  183. {
  184.   if (cred->cr_uid == 0)
  185.     return 0;
  186.   return EPERM;
  187. }
  188.  
  189. /*
  190.  * Search credentials
  191.  */
  192. static struct pcred *crfind(pid_t pid)
  193. {
  194.   return procfind(pid)->p_cred;
  195. }
  196.  
  197. /****** usergroup.library/getuid *********************************************
  198.  
  199.     NAME
  200.         getuid, geteuid - get user process identification
  201.         getgid, getegid - get group process identification
  202.  
  203.     SYNOPSIS
  204.         ruid = getuid()
  205.         D0
  206.  
  207.         uid_t getuid(void);
  208.  
  209.         euid = geteuid()
  210.         D0
  211.  
  212.         uid_t geteuid(void);
  213.  
  214.         rgid = getgid()
  215.         D0
  216.  
  217.         gid_t getgid(void);
  218.  
  219.         egid = getegid()
  220.         D0
  221.  
  222.         gid_t getegid(void);
  223.  
  224.     FUNCTION
  225.         The getuid() function returns the real user ID of the calling
  226.         process, geteuid() returns the effective user ID of the calling
  227.         process.
  228.  
  229.         The getgid() function returns the real group ID of the calling
  230.         process, getegid() returns the effective group ID of the calling
  231.         process.
  232.  
  233.         The real user ID and real group ID is specified at login time.
  234.  
  235.         The real ID is the ID of the user who invoked the program.  As the
  236.         effective user and gourp ID gives the process additional permissions
  237.         during the execution of `set-user-ID' or `set-group-ID' mode
  238.         programs, functions getgid() and getuid () are used to determine the
  239.         real-ids of the calling process.
  240.  
  241.     RESULT
  242.         The getuid(), geteuid(), getgid(), and getegid() functions are
  243.         always successful, and no return value is reserved to indicate an
  244.         error.
  245.  
  246.     NOTES
  247.         Any task can call these functions
  248.  
  249.     SEE ALSO
  250.         getgroups(), setuid(), setreuid(), setgid(), setregid(), setgroups()
  251.  
  252. ******************************************************************************
  253. */
  254.  
  255. SAVEDS ASM uid_t R_getuid(void)
  256. {
  257.   return crfind(NULL)->p_ruid;
  258. }
  259.  
  260. SAVEDS ASM uid_t R_geteuid(void)
  261. {
  262.   return crfind(NULL)->p_euid;
  263. }
  264.  
  265. SAVEDS ASM gid_t R_getgid(void)
  266. {
  267.   return crfind(NULL)->p_rgid;
  268. }
  269.  
  270. SAVEDS ASM gid_t R_getegid(void)
  271. {
  272.   return crfind(NULL)->p_egid;
  273. }
  274.  
  275. /****** usergroup.library/getgroups *******************************************
  276.  
  277.     NAME
  278.         getgroups - get group access list
  279.  
  280.     SYNOPSIS
  281.         len = getgroups(gidsetlen, gidset[])
  282.         D0              D0         A0
  283.  
  284.         int getgroups(int, gid_t *);
  285.  
  286.     FUNCTION
  287.         Getgroups() gets the current group access list of the user process
  288.         and stores it in the array gidset. The parameter gidsetlen indicates
  289.         the number of entries that may be placed in gidset. The function
  290.         getgroups() returns the actual number of groups returned in gidset.
  291.         No more than NGROUPS, as defined in <libraries/usergroup.h>, will
  292.         ever be returned.
  293.  
  294.      RESULT
  295.         A successful call returns the number of groups in the group set.  A
  296.         value of -1 indicates that the argument gidsetlen is smaller than
  297.         the number of groups in the group set.
  298.  
  299.     ERRORS
  300.         [EINVAL] The argument gidsetlen is smaller than the number of
  301.                  groups in the group set.
  302.         [EFAULT] The argument gidset specifies an invalid address.
  303.  
  304.     SEE ALSO
  305.         setgroups(), initgroups(), getgid(), getegid()
  306.  
  307.     HISTORY
  308.         The getgroups function call appeared in 4.2BSD.
  309.  
  310. ****************************************************************************
  311. */
  312.  
  313. SAVEDS ASM int R_getgroups(REG(d0) int ngroups, REG(a1) gid_t *groups)
  314. {
  315.   struct pcred *pc = crfind(NULL);
  316.   gid_t *getgroups;
  317.   short error;
  318.  
  319.   if (ngroups == 0) {
  320.     return pc->p_ngroups;
  321.   } else if (ngroups < pc->p_ngroups) {
  322.     error = EINVAL;
  323.   } else if (groups == NULL || ((LONG)groups & 1) != 0) {
  324.     error = EFAULT;
  325.   } else {
  326.     /* This does also UWORD -> gid_t conversion */
  327.     getgroups = pc->p_groups;
  328.     ngroups = pc->p_ngroups;
  329.     while (ngroups-- > 0) {
  330.       *groups++ = *getgroups++;
  331.     }
  332.     return pc->p_ngroups;
  333.   }
  334.  
  335.   SetErrno(error);
  336.   return -1;
  337. }
  338.  
  339. /****** usergroup.library/setuid ***********************************************
  340.  
  341.     NAME
  342.         setuid, setreuid - set real and effective user ID's
  343.         setgid, setregid - set real and effective group ID's
  344.  
  345.     SYNOPSIS
  346.         success = setuid(uid)
  347.         D0               D0
  348.  
  349.         int setuid(uid_t);
  350.  
  351.         success = setreuid(ruid, euid);
  352.         D0                 D0    D1
  353.  
  354.         int setreuid(uid_t, uid_t);
  355.  
  356.         success = setgid(gid)
  357.         D0               D0
  358.  
  359.         int setgid(gid_t);
  360.  
  361.         success = setregid(ruid, euid)
  362.         D0                 D0    D1
  363.  
  364.         int setregid(gid_t ruid, gid_t euid);
  365.  
  366.     FUNCTION
  367.         The real and effective ID's of the current process are set according
  368.         to the arguments.  If ruid or euid is -1, the current uid is filled
  369.         in by the system.  Unprivileged users may change the real ID to the
  370.         effective ID and vice-versa; only the super-user may make other
  371.         changes.
  372.  
  373.     RETURN VALUES
  374.         Upon successful completion, a value of 0 is returned. Otherwise, a
  375.         value of -1 is returned and errno is set to indicate the error.
  376.  
  377.     ERRORS
  378.         [EPERM]  The current process is not the super-user and a change
  379.                  other than changing the effective id to the real id was
  380.                  specified.
  381.  
  382.     SEE ALSO
  383.         getuid(), getgid(), geteuid(), getegid()
  384.  
  385.     NOTES
  386.         Any task can call these functions.
  387.  
  388.     HISTORY
  389.         A setuid() and setgid() function calls appeared in Version 6 AT&T
  390.         UNIX.  The setreuid() and setregid() function calls appeared in
  391.         4.2BSD.
  392.  
  393. ****************************************************************************
  394. */
  395.  
  396. SAVEDS ASM int R_setuid(REG(d0) uid_t uid)
  397. {
  398.   return R_setreuid(uid, uid);
  399. }
  400.  
  401. SAVEDS ASM int R_setreuid(REG(d0) uid_t ruid, REG(d1) uid_t euid)
  402. {
  403.   struct pcred *pc = crfind(NULL);
  404.   short error;
  405.  
  406.   if (ruid == NOID)
  407.     ruid = pc->p_ruid;
  408.   if (euid == NOID)
  409.     euid = pc->pc_ucred->cr_uid;
  410.  
  411.   /*
  412.    * Allow setting real uid to previous effective, for swapping real and
  413.    * effective.  This should be:
  414.    *
  415.    * if (ruid != pc->p_ruid &&
  416.    *     (error = suser(pc->pc_ucred, &p->p_acflag)))
  417.    */
  418. #if 1
  419.   /* allow setreuid(-1, 0) to emulate SUID */
  420.   if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
  421.        (error = suser(pc->pc_ucred))) ||
  422.       (/* euid != pc->pc_ucred->cr_uid */ 0 && euid != pc->p_ruid &&
  423.        (error = suser(pc->pc_ucred))))
  424. #else
  425.   if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
  426.        (error = suser(pc->pc_ucred))) ||
  427.       (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
  428.        (error = suser(pc->pc_ucred))))
  429. #endif
  430.     {
  431.       unlock(&credential_list);
  432.       SetErrno(error);
  433.       return -1;
  434.     } else {
  435.     /*
  436.      * Everything's okay, do it.  Copy credentials so other references do
  437.      * not see our changes.
  438.      */
  439.     pc->pc_ucred = crcopy(pc->pc_ucred);
  440.     pc->pc_ucred->cr_uid = euid;
  441.     pc->p_ruid = ruid;
  442.  
  443.     return 0;
  444.   }
  445. }
  446.  
  447. SAVEDS ASM int R_setgid(REG(d0) gid_t gid)
  448. {
  449.   return R_setregid(gid, gid);
  450. }
  451.  
  452. SAVEDS ASM int R_setregid(REG(d0) gid_t rgid, REG(d1) gid_t egid)
  453. {
  454.   struct pcred *pc = crfind(NULL);
  455.   short error;
  456.  
  457.   if (rgid == NOID)
  458.     rgid = pc->p_rgid;
  459.   if (egid == NOID)
  460.     egid = pc->pc_ucred->cr_gid;
  461.  
  462.   /*
  463.    * Allow setting real gid to previous effective, for swapping real and
  464.    * effective.  This should be:
  465.    *
  466.    * if (rgid != pc->p_rgid &&
  467.    *     (error = suser(pc->pc_ucred, &p->p_acflag)))
  468.    */
  469.   if ((rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_gid /* XXX */ &&
  470.        (error = suser(pc->pc_ucred))) ||
  471.       (egid != pc->pc_ucred->cr_gid && egid != pc->p_rgid &&
  472.        (error = suser(pc->pc_ucred)))) {
  473.     SetErrno(error);
  474.     return -1;
  475.   } else {
  476.     /*
  477.      * Everything's okay, do it.  Copy credentials so other references do
  478.      * not see our changes.
  479.      */
  480.     pc->pc_ucred = crcopy(pc->pc_ucred);
  481.     pc->pc_ucred->cr_gid = egid;
  482.     pc->p_rgid = rgid;
  483.  
  484.     return 0;
  485.   }
  486. }
  487.  
  488. /****** usergroup.library/setgroups ******************************************
  489.  
  490.     NAME
  491.         setgroups - set group access list
  492.  
  493.     SYNOPSIS
  494.         success = setgroups(ngroups, gidset)
  495.         D0                  D0       A0
  496.  
  497.         int setgroups(int, const gid_t *);
  498.  
  499.     FUNCTION
  500.         Setgroups() sets the group access list of the current user process
  501.         according to the array gidset. The parameter ngroups indicates the
  502.         number of entries in the array and must be no more than NGROUPS, as
  503.         defined in <libraries/usergroup.h>.
  504.  
  505.         Only the super-user may set new groups. The super-user can not
  506.         set illegal groups (-1).
  507.  
  508.     RESULT
  509.         A 0 value is returned on success, -1 on error, with an error
  510.         code stored in errno and available with ug_GetErr() function.
  511.  
  512.     ERRORS
  513.         [EINVAL]    An illegal group id was specified.
  514.         [EPERM]     The caller has got no necessary privileges.
  515.         [EFAULT]    The address specified for gidset is illegal.
  516.  
  517.     NOTES
  518.         Any task can call this function.
  519.  
  520.     SEE ALSO
  521.         getgroups(), initgroups()
  522.  
  523. ****************************************************************************
  524. */
  525.  
  526. SAVEDS ASM int R_setgroups(REG(d0) int ngrp,
  527.                REG(a1) const gid_t *groups)
  528. {
  529.   register struct pcred *pc = crfind(NULL);
  530.   register gid_t *gp;
  531.   register const gid_t *lp;
  532.   short error;
  533.  
  534.   if (error = suser(pc->pc_ucred /*, &p->p_acflag */)) {
  535.  
  536.   } else if (ngrp > NGROUPS) {
  537.     error = EINVAL;
  538.   } else if (groups == NULL || ((LONG)groups & 1) != 0) {
  539.     error = EFAULT;
  540.   } else {
  541.     pc->pc_ucred = crcopy(pc->pc_ucred);
  542.     pc->pc_ucred->cr_ngroups = ngrp;
  543.     for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
  544.       *gp++ = *lp++;
  545.     return 0;
  546.   }
  547.  
  548.   SetErrno(error);
  549.   return -1;
  550. }
  551.  
  552.  
  553. /****** usergroup.library/MU2UG **********************************************
  554.  
  555.     NAME
  556.         MU2ID - macro converting MultiUser id to usergroup id
  557.         ID2MU - macro converting usergroup id to MultiUser id
  558.  
  559.     SYNOPSIS
  560.         ug_id = MU2ID(mu_id)
  561.  
  562.         mu_id = ID2MU(ug_id)
  563.  
  564.     FUNCTION
  565.         These macros are used to convert between different user ID
  566.         formats.  The mu_id is in the format used by MultiUser filesystem
  567.         and multiuser.library.  The ug_id is the format used by Unix and
  568.         usergroup.library.
  569.  
  570.         Most of the id values are identical in usergroup.library and
  571.         multiuser.library. However, these two exceptions have values as
  572.         follows:
  573.  
  574.                     usergroup.library  multiuser.library
  575.         super-user          0              65535
  576.         nobody             -2                  0
  577.  
  578.     INPUTS AND RESULTS
  579.         mu_id    - user ID in MultiUser format.
  580.         ug_id    - user ID in usergroup format.
  581.  
  582.     BUGS
  583.         The usergroup id values that won't fit into UWORD are truncated.
  584.  
  585.     SEE ALSO
  586. ******************************************************************************
  587. */
  588.  
  589. #if 0
  590. ASM uid_t R_ug_mu2id(REG(d0) UWORD id)
  591. {
  592.   if (id == 0) {
  593.     return -2;
  594.   } else if (id == 65535) {
  595.     return 0;
  596.   } else {
  597.     return id;
  598.   }
  599. }
  600.  
  601. ASM UWORD R_ug_id2mu(REG(d0) uid_t id)
  602. {
  603.   if (id == 0) {
  604.     return 65535;
  605.   } else if (id == -2) {
  606.     return 0;
  607.   } else {
  608.     return id;
  609.   }
  610. }
  611. #endif
  612.  
  613. /****** usergroup.library/umask *********************************************
  614.  
  615.     NAME
  616.         umask - set file creation mode mask
  617.  
  618.     SYNOPSIS
  619.         #include <sys/stat.h>
  620.  
  621.         oldmask = umask(newmask)
  622.     D0              D0
  623.  
  624.         mode_t umask(mode_t);
  625.  
  626.     FUNCTION
  627.         The umask() routine sets the process's file mode creation mask to
  628.         numask and returns the previous value of the mask.  The 9 low-order
  629.         access permission bits of numask are used by Unix-compatible
  630.         filesystems, for examble by NFS, to turn off corresponding bits
  631.         requested in file mode.  This clearing allows each user to restrict
  632.         the default access to his files.
  633.  
  634.         The default mask value is 022 (write access for owner only).  Child
  635.         processes should inherit the mask of the calling process.
  636.  
  637.     RESULT
  638.         The previous value of the file mode mask is returned by the call.
  639.  
  640.     ERRORS
  641.         The umask() function is always successful.
  642.  
  643.     SEE ALSO
  644.         getumask()
  645. ******************************************************************************
  646. */
  647.  
  648. SAVEDS ASM mode_t R_umask(REG(d0) mode_t newmask)
  649. {
  650.   struct proc *p = procfind(NULL);
  651.  
  652.   mode_t oldmask = p->p_umask;
  653.  
  654.   p->p_umask = newmask;
  655.  
  656.   return oldmask ;
  657. }
  658.  
  659. /****** usergroup.library/getumask *********************************************
  660.  
  661.     NAME
  662.         getumask - get file creation mode mask
  663.  
  664.     SYNOPSIS
  665.         #include <sys/stat.h>
  666.  
  667.         oldmask = getumask()
  668.     D0
  669.  
  670.         mode_t getumask(void);
  671.  
  672.     FUNCTION
  673.         The getumask() routine sets the process's file mode creation mask to
  674.         numask and returns the previous value of the mask.  The 9 low-order
  675.         access permission bits of numask are used by Unix-compatible
  676.         filesystems, for examble by NFS, to turn off corresponding bits
  677.         requested in file mode.
  678.  
  679.     RESULT
  680.         The value of the file mode mask is returned by the call.
  681.  
  682.     ERRORS
  683.         The getumask() function is always successful.
  684.  
  685.     SEE ALSO
  686.         umask()
  687. ******************************************************************************
  688. */
  689.  
  690. SAVEDS ASM mode_t R_getumask(void)
  691. {
  692.   struct proc *p = procfind(NULL);
  693.  
  694.   return p->p_umask;
  695. }
  696.  
  697.  
  698. /****** usergroup.library/getcredentials *************************************
  699.  
  700.     NAME
  701.         getcredentials -- get credentials of given task. (V4)
  702.  
  703.     SYNOPSIS
  704.         #include <libraries/usergroup.h>
  705.  
  706.         credentials = getcredentials(task)
  707.     D0                              A0
  708.  
  709.         struct UserGroupCredentials *getcredentials(struct Task *);
  710.  
  711.     FUNCTION
  712.     The function getcredentials() returns all credentials of the given
  713.         task.  The credentials include real and effective user and group IDs,
  714.         umask, login name and session ID.  If the task pointer is NULL, the
  715.         credentials of current task are returned.
  716.  
  717.     RESULT
  718.         A getcredentials() function returns a valid pointer to structure
  719.         UserGroupCredentials on success and a null pointer if an error
  720.         occurs.
  721.  
  722.     ERRORS
  723.         [EINVAL]    An illegal task pointer was specified.
  724.  
  725.     BUGS
  726.         This function leave its result in an internal static object and
  727.         return a pointer to that object. Subsequent calls to this function
  728.         will modify the same object.
  729.  
  730.     SEE ALSO
  731.  
  732. ******************************************************************************
  733. */
  734.  
  735. static struct UserGroupCredentials creds[1];
  736.  
  737. SAVEDS ASM struct UserGroupCredentials
  738.   *R_getcredentials(REG(a0) struct Task *task)
  739. {
  740.   register struct proc *p = procfind(task);
  741.  
  742.   if (p != NULL) {
  743.     register struct UserGroupCredentials *c = creds;
  744.  
  745.     c->cr_ruid  = p->p_cred->p_ruid;
  746.     c->cr_rgid  = p->p_cred->p_rgid;
  747.     c->cr_umask = p->p_umask;
  748.     c->cr_euid  = p->p_cred->p_euid;
  749.     c->cr_ngroups = p->p_cred->p_ngroups;
  750.     c->cr_session = p->p_session->s_leader;
  751.     memcpy(c->cr_groups, p->p_cred->p_groups, sizeof(c->cr_groups));
  752.     memcpy(c->cr_login, p->p_session->s_login, sizeof(c->cr_login));
  753.  
  754.     return c;
  755.   }
  756.  
  757.   return NULL;
  758. }
  759.